package com.travel.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.travel.common.Result;
import com.travel.domain.DTO.MailDTO;
import com.travel.domain.DTO.UserInfoUpdateDTO;
import com.travel.domain.DTO.UserLoginDTO;
import com.travel.domain.VO.UserInfoVO;
import com.travel.domain.VO.UserLoginVO;
import com.travel.domain.entity.User;
import com.travel.exception.UnauthorizedException;
import com.travel.service.UserService;
import com.travel.utils.AliOssUtil;
import com.travel.utils.BaseContext;
import com.travel.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @Autowired
    private AliOssUtil aliOssUtil;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private static final String USER_CACHE_KEY_PREFIX = "user:";


    @GetMapping("/login/{code}")
    public Result<UserLoginVO> login(@PathVariable  String code){
        log.info("微信用户登录：{}",code);

        //微信登录
        User user = userService.wxLogin(code);


        //为微信用户生成jwt令牌
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId",user.getId());
        String token = JwtUtils.generateJwt(claims);

        UserLoginVO userLoginVO = UserLoginVO.builder()
                .id(user.getId())
                .openid(user.getOpenid())
                .token(token)
                .build();
        return Result.success(userLoginVO);
    }

    // 获取用户信息并缓存
    @GetMapping("/getUserInfo")
    public Result<UserInfoVO> getUserInfo() {
        Long userId = BaseContext.getCurrentId();
        String cacheKey = USER_CACHE_KEY_PREFIX + userId;
        // 先尝试从缓存中获取
        UserInfoVO userInfo = (UserInfoVO) redisTemplate.opsForValue().get(cacheKey);
        if (userInfo != null) {
            return Result.success(userInfo);
        }
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getId,userId);
        User user = userService.getOne(wrapper);
        UserInfoVO userInfoVO = UserInfoVO.builder()
                .name(user.getName())
                .avatar(user.getAvatar())
                .email(user.getEmail())
                .build();
        // 将查询到的结果放入缓存，设置过期时间为1小时
        redisTemplate.opsForValue().set(cacheKey, userInfoVO, 1, TimeUnit.HOURS);
        return Result.success(userInfoVO);
    }

    @PostMapping("/updateUserInfo")
    public Result<String> updateUserInfo(@RequestBody UserInfoUpdateDTO userInfoUpdateDTO) {
        Long userId = BaseContext.getCurrentId(); // 从上下文中获取当前用户ID

        if (userId == null) {
            return Result.error("用户未登录");
        }

        // 如果传递了验证码，先进行验证码验证
        if (userInfoUpdateDTO.getCode() != null && !userInfoUpdateDTO.getCode().trim().isEmpty()) {
            String email = userInfoUpdateDTO.getEmail();
            if (email == null || email.trim().isEmpty()) {
                return Result.error("邮箱不能为空");
            }

            // 调用验证码验证方法
            boolean verificationResult = verifyCode(email, userInfoUpdateDTO.getCode());
            if (!verificationResult) {
                return Result.error("认证失败");
            }
        }

        // 验证通过后继续执行用户信息更新
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getId, userId); // 条件：根据用户ID

        // 使用 condition 判断字段是否需要更新
        updateWrapper.set(userInfoUpdateDTO.getName() != null && !userInfoUpdateDTO.getName().trim().isEmpty(),
                User::getName, userInfoUpdateDTO.getName());
        updateWrapper.set(userInfoUpdateDTO.getAvatar() != null && !userInfoUpdateDTO.getAvatar().trim().isEmpty(),
                User::getAvatar, userInfoUpdateDTO.getAvatar());
        updateWrapper.set(userInfoUpdateDTO.getEmail() != null && !userInfoUpdateDTO.getEmail().trim().isEmpty(),
                User::getEmail, userInfoUpdateDTO.getEmail());

        // 执行更新
        boolean isUpdated = userService.update(updateWrapper);

        if (isUpdated) {
            log.info("用户信息更新成功，用户ID: {}", userId);
            return Result.success("用户信息更新成功");
        } else {
            log.error("用户信息更新失败，用户ID: {}", userId);
            return Result.error("用户信息更新失败");
        }
    }



    /**
     * 上传头像
     * @param file
     * @return
     */
    @PostMapping("/upload")
    public Result<String> upload(MultipartFile file){
        log.info("文件上传：{}",file);

        try {
            //原始文件名
            String originalFilename = file.getOriginalFilename();
            //截取原始文件名的后缀   xxx.png
            String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
            // 文件夹路径
            String folder = "小程序头像/";
            //构造新文件名称
            String objectName = folder + UUID.randomUUID().toString() + extension; // 完整路径
            //文件的请求路径
            String filePath = aliOssUtil.upload(file.getBytes(), objectName);

            UserInfoUpdateDTO userUpdateDTO = UserInfoUpdateDTO.builder()
                    .avatar(filePath)
                    .build();
            updateUserInfo(userUpdateDTO);
            return Result.success(filePath);
        } catch (IOException e) {
            log.error("文件上传失败：{}", e);
        }
        return Result.error("上传失败！");
    }
    public boolean verifyCode(String mail, String code) {
        // 从 Redis 获取验证码
        String redisCode = (String)redisTemplate.opsForValue().get("email:code:" + mail);

        if (redisCode == null) {
            return false;
        }

        if (!redisCode.equals(code)) {
            return false;
        }

        // 验证成功后，可以清除 Redis 中的验证码
        redisTemplate.delete("email:code:" + mail);

        return true;
    }

}
